package LinkerLoader;

/**
 * This class creates a load map.
 * @author Aashish kumar
 */
public class LoadMap {
    static String[][] load_map;
    
    /**
     * This function calculates the location where each program gets loaded into the memory.<p>
     * Modified Log: None.<br>
     * Error Condition tested: None.<br>
     * Creation Date : May 27,2008.<br>
     * Original Author: Aashish Kumar.<br>
     * @param file_address a String[] containing the address of each of the linker's input file.
     * @return Returns an int[] containing the address of memory location where each program is loaded.
     */
    public int[] getOffsetLoadMap(String[] file_address){
        Linker linker_instance = new Linker();
        int[] offset = new int[file_address.length];
        offset[0]=0;//default location for first program.
        for(int index=1; index<offset.length; index++){
            offset[index]=offset[index-1]+linker_instance.readFile(file_address[index-1],"T").length;
        }
        return offset;
    }
    
    /**
     * This function deducts the start of the program address from the address of the memory location in the hex_code
     * and adds the correction factor to get the new hex_code.<p>
     * Modified Log: <br>
     * May 29,2008 - some coding errors removed - Aashish Kumar.<br>
     * Error Condition tested: None.<br>
     * Creation Date : May 27,2008.<br>
     * Original Author: Aashish Kumar.<br>
     * @param hex_code a 4 bit hex_code
     * @param start_of_program_offset - a 4 bit hex_code
     * @param correction - any integer
     * @return Returns the new hex_code
     */
    public String offsetCorrection(String hex_code, String start_of_program_offset, int correction){
        int int_value = Integer.parseInt(hex_code,16);
        String bin_value = new IceAssembly.Convert().getBitCode(String.valueOf(int_value), 16);
        String first_5_bits = bin_value.substring(0,5);
        String rest_bits = bin_value.substring(5);
        if(rest_bits.charAt(1)=='0'){
            int int_rest_bits = Integer.parseInt(rest_bits,2);
            int corrected_rest_bits = int_rest_bits-Integer.parseInt(start_of_program_offset,16)+correction;
            String corrected_bin_code = first_5_bits+(new IceAssembly.Convert().getBitCode(String.valueOf(corrected_rest_bits), 11));
            hex_code = new IceAssembly.Convert().intToFourHex(Integer.parseInt(corrected_bin_code,2));
            return hex_code;
        }else{
            char[] six_to_last = rest_bits.substring(2).toCharArray();
            for(int index=0;index<six_to_last.length;index++){
                if(six_to_last[index]=='1'){
                    six_to_last[index]='0';
                }else{
                    six_to_last[index]='1';
                }
            }
            hex_code = new IceAssembly.Convert().intToFourHex(Integer.parseInt(String.valueOf(six_to_last))+1);
            return hex_code;
        }
    }
    
    /**
     * This function deducts the start of the program address from the address of the memory location in the hex_code
     * and adds the correction factor to get the new hex_code.<p>
     * Modified Log: <br>
     * May 29,2008 - some coding errors removed - Aashish Kumar.<br>
     * Error Condition tested: None.<br>
     * Creation Date : May 27,2008.<br>
     * Original Author: Aashish Kumar.<br>
     * @param hex_code a 4 bit hex_code
     * @param start_of_program_offset - a 4 bit hex_code
     * @param correction - any integer
     * @return Returns the new hex_code
     */
    public int correctionInt(String hex_code){
        int int_value = Integer.parseInt(hex_code,16);
        String bin_value = new IceAssembly.Convert().getBitCode(String.valueOf(int_value), 16);
        String first_5_bits = bin_value.substring(0,5);
        String rest_bits = bin_value.substring(5);
        if(rest_bits.charAt(1)=='0'){
            return Integer.parseInt(hex_code, 16);
        }else{
            char[] six_to_last = rest_bits.substring(2).toCharArray();
            for(int index=0;index<six_to_last.length;index++){
                if(six_to_last[index]=='1'){
                    six_to_last[index]='0';
                }else{
                    six_to_last[index]='1';
                }
            }
            return -(Integer.parseInt(String.valueOf(six_to_last),2)+1);
        }
    }
    
    /**
     * This function calculates the sum of the number of Linking records in the files input to the linker.<p>
     * Modified Log: None.<br>
     * Error Condition tested: None.<br>
     * Creation Date : May 27,2008.<br>
     * Original Author: Aashish Kumar.<br>
     * @param file_address a String[] containing the address of each of the linker's input file.
     * @return the length of the load map.
     */
    public int getLoadMapLength(String[] file_address){
        Linker linker_instance = new Linker();
        int load_map_length=0;
        for(int index=0; index<file_address.length; index++){
            load_map_length+=linker_instance.readFile(file_address[index],"L").length;
        }
        return load_map_length;
    }
    
    /**
     * This function sets the load map.
     * Modified Log: None.<br>
     * Error Condition tested: None.<br>
     * Creation Date : May 27,2008.<br>
     * Original Author: Aashish Kumar.<br>
     * @param file_address a String[] containing the address of each of the linker's input file.
     */
    public void setLoadMap(String[] file_address){
        int[] offset = getOffsetLoadMap(file_address);
        Linker linker_instance = new Linker();
        load_map = new String[getLoadMapLength(file_address)][4]; int load_map_counter=0;
        for(int index=0; index<file_address.length; index++){
            String[][] temp = linker_instance.readFile(file_address[index],"L");
            for(int index2=0; index2<temp.length; index2++){
                load_map[load_map_counter] = temp[index2];
                load_map[load_map_counter][2] = offsetCorrection(load_map[load_map_counter][2],linker_instance.readFile(file_address[index], "H")[0][3],offset[index]);
                load_map_counter++;
            }
        }
    }
}